package model

import (
	"fmt"
	"strings"
	"sync"
	"time"
)

type Respondent struct {
	Id int64 `xorm:"pk autoincr"`
	Type int
	Flavor string
	Specifications string
	RespondentOffer RespondentOffer `xorm:"-"`
	//RespondentOfferList []*RespondentOffer
	CreatedAt time.Time
	UpdatedAt time.Time
}

type RespondentOffer struct {
	Id int64 `xorm:"pk autoincr"`
	RespondentId int64
	FlavorSpecificationsList []*FlavorSpecifications `xorm:"-"`
	OfferGradientList []*OfferGradient `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type OfferGradient struct {
	Interval int64 `xorm:"pk autoincr"`
	RespondentOfferId int64
	Minv float64
	Maxv float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type MaterielType struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	MaterielList []*Materiel `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Materiel struct {
	Id int64 `xorm:"pk autoincr"`
	Type int
	Name string
	FlavorSpecificationsId int64
	FirstInterval float64
	SecondInterval float64
	ThirdInterval float64
	FourthInterval float64
	FifthInterval float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type FlavorSpecifications struct {
	Id int64 `xorm:"pk autoincr"`
	RespondentOfferId int64
	Name string
	QuotationDetails []*MaterielType `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (sr *Respondent)InsertRespondent(rId int64){
	var r Respondent
	x.Where("id = ?", rId).Get(&r)
	var ro RespondentOffer
	ro.RespondentId = r.Id
	ro.CreatedAt = time.Now()
	ro.UpdatedAt = time.Now()
	x.Insert(&ro)

	var mts []*MaterielType
	x.Find(&mts)
	fmt.Println(len(mts))
	for _, mv := range mts {
		x.Where("type = ?", mv.Id).And("id <= ?", 10022).Find(&mv.MaterielList)
		fmt.Println(len(mv.MaterielList))
	}

	flavorList := strings.Split(r.Flavor, "，")
	specificationsList := strings.Split(r.Specifications, "，")
	for _, fv := range flavorList{
		for _, sv := range specificationsList{
			var fs FlavorSpecifications
			fs.RespondentOfferId = ro.Id
			fs.Name = fv+" "+sv
			fs.CreatedAt = time.Now()
			fs.UpdatedAt = time.Now()
			x.Insert(&fs)

			for _, mv := range mts{
				for _, v := range mv.MaterielList{
					//var m Materiel
					//m.Name =v.Name
					//m.Type = v.Type
					v.Id = 0
					v.FlavorSpecificationsId = fs.Id
					v.CreatedAt = time.Now()
					v.UpdatedAt = time.Now()
					x.Insert(v)
					fmt.Println("插入之后：", v.Id)
				}
			}
		}
	}
}

func (sr *Respondent)InsertRespondentAsync(rId int64, wg *sync.WaitGroup){
	var r Respondent
	x.Where("id = ?", rId).Get(&r)
	var ro RespondentOffer
	ro.RespondentId = r.Id
	ro.CreatedAt = time.Now()
	ro.UpdatedAt = time.Now()
	x.Insert(&ro)

	var mts []*MaterielType
	x.Find(&mts)
	fmt.Println(len(mts))

	go func() {
		defer func() {
			// 捕获异常 防止waitGroup阻塞
			if err := recover(); err != nil {
				wg.Done()
			}
		}()

		for _, mv := range mts {
			x.Where("type = ?", mv.Id).And("id <= ?", 10022).Find(&mv.MaterielList)
		}

		wg.Done()
	}()

	flavorList := strings.Split(r.Flavor, "，")
	specificationsList := strings.Split(r.Specifications, "，")

	for i := 0; i < 4; i++ {
		actual := i
		go func() {
			defer func() {
				// 捕获异常 防止waitGroup阻塞
				if err := recover(); err != nil {
					wg.Done()
				}
			}()

			fv := flavorList[actual]
			for _, sv := range specificationsList {
				var fs FlavorSpecifications
				fs.RespondentOfferId = ro.Id
				fs.Name = fv + " " + sv
				fs.CreatedAt = time.Now()
				fs.UpdatedAt = time.Now()
				x.Insert(&fs)

				for _, mv := range mts {
					for _, v := range mv.MaterielList {
						//var m Materiel
						//m.Name =v.Name
						//m.Type = v.Type
						v.Id = 0
						v.FlavorSpecificationsId = fs.Id
						v.CreatedAt = time.Now()
						v.UpdatedAt = time.Now()
						x.Insert(v)
					}
				}
			}

			wg.Done()
		}()
	}
}

func BubbleSort(arr []*OfferGradient) []*OfferGradient{
	for i := 0; i < len(arr)-1; i++ {
		for j := 0; j < len(arr)-i-1; j++ {
			if arr[j].Maxv > arr[j+1].Maxv {
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
		}
	}
	fmt.Println(arr)
	return arr
}

func (sr *Respondent)QueryRespondentOffer(rId int64)(*Respondent, error){

	sr.InsertRespondent(rId)

	var r Respondent
	x.Where("id = ?", rId).Get(&r)
	x.Where("respondent_id = ?", r.Id).Limit(1).Get(&r.RespondentOffer)

	x.Where("respondent_offer_id = ?", r.RespondentOffer.Id).Find(&r.RespondentOffer.OfferGradientList)
	r.RespondentOffer.OfferGradientList = BubbleSort(r.RespondentOffer.OfferGradientList)

	x.Where("respondent_offer_id = ?", r.RespondentOffer.Id).Find(&r.RespondentOffer.FlavorSpecificationsList)
	for _, rfsv := range r.RespondentOffer.FlavorSpecificationsList{
		x.Find(&rfsv.QuotationDetails)
		for _, qv := range rfsv.QuotationDetails{
			x.Where("type = ?", qv.Id).And("flavor_specifications_id = ?", rfsv.Id).Find(&qv.MaterielList)
		}
	}
	return &r, nil
}

func (sr *Respondent)QueryRespondentOfferAsync(rId int64)(*Respondent, error){

	var wg sync.WaitGroup
	wg.Add(11)

	sr.InsertRespondentAsync(rId, &wg)

	var r Respondent
	x.Where("id = ?", rId).Get(&r)
	x.Where("respondent_id = ?", r.Id).Limit(1).Get(&r.RespondentOffer)

	x.Where("respondent_offer_id = ?", r.RespondentOffer.Id).Find(&r.RespondentOffer.OfferGradientList)
	r.RespondentOffer.OfferGradientList = BubbleSort(r.RespondentOffer.OfferGradientList)

	x.Where("respondent_offer_id = ?", r.RespondentOffer.Id).Find(&r.RespondentOffer.FlavorSpecificationsList)

	for i := 0; i < 6; i++ {
		actuall := i
		go func() {
			defer func() {
				// 捕获异常 防止waitGroup阻塞
				if err := recover(); err != nil {
					wg.Done()
				}
			}()

			for _, rfsv := range r.RespondentOffer.FlavorSpecificationsList[actuall*2:(actuall+1)*2] {
				x.Find(&rfsv.QuotationDetails)
				for _, qv := range rfsv.QuotationDetails {
					x.Where("type = ?", qv.Id).And("flavor_specifications_id = ?", rfsv.Id).Find(&qv.MaterielList)
				}
			}

			wg.Done()
		}()
	}

	wg.Wait()

	return &r, nil
}

func (sr *Respondent)SaveRespondentOffer(r *Respondent)(map[string]interface{}, error){

	r.RespondentOffer.Id = 0
	r.RespondentOffer.CreatedAt = time.Now()
	r.RespondentOffer.UpdatedAt = time.Now()
	x.Insert(&r.RespondentOffer)

	for _, ov := range r.RespondentOffer.OfferGradientList{
		ov.Interval = 0
		ov.RespondentOfferId = r.RespondentOffer.Id
		ov.CreatedAt = time.Now()
		ov.UpdatedAt = time.Now()
		x.Insert(ov)
	}

	for _, rfsv := range r.RespondentOffer.FlavorSpecificationsList{
		rfsv.Id = 0
		rfsv.RespondentOfferId = r.RespondentOffer.Id
		rfsv.CreatedAt = time.Now()
		rfsv.UpdatedAt = time.Now()
		x.Insert(rfsv)
		for _, qv := range rfsv.QuotationDetails{
			for _, mv := range qv.MaterielList{
				mv.Id = 0
				mv.FlavorSpecificationsId = rfsv.Id
				mv.CreatedAt = time.Now()
				mv.UpdatedAt = time.Now()
				x.Insert(mv)
			}
		}
	}
	return map[string]interface{}{"message":"成功", "code":200}, nil
}

func (sr *Respondent)SaveRespondentOfferAsync(r *Respondent)(map[string]interface{}, error){

	r.RespondentOffer.Id = 0
	r.RespondentOffer.CreatedAt = time.Now()
	r.RespondentOffer.UpdatedAt = time.Now()
	x.Insert(&r.RespondentOffer)

	var wg sync.WaitGroup
	wg.Add(7)

	go func() {
		defer func() {
			// 捕获异常 防止waitGroup阻塞
			if err := recover(); err != nil {
				wg.Done()
			}
		}()

		for _, ov := range r.RespondentOffer.OfferGradientList {
			ov.Interval = 0
			ov.RespondentOfferId = r.RespondentOffer.Id
			ov.CreatedAt = time.Now()
			ov.UpdatedAt = time.Now()
			x.Insert(ov)
		}

		wg.Done()
	}()

	for i := 0; i < 6; i++ {
		actual := i
		go func() {
			defer func() {
				// 捕获异常 防止waitGroup阻塞
				if err := recover(); err != nil {
					wg.Done()
				}
			}()

			for _, rfsv := range r.RespondentOffer.FlavorSpecificationsList[actual*2:(actual+1)*2] {
				rfsv.Id = 0
				rfsv.RespondentOfferId = r.RespondentOffer.Id
				rfsv.CreatedAt = time.Now()
				rfsv.UpdatedAt = time.Now()
				x.Insert(rfsv)
				for _, qv := range rfsv.QuotationDetails {
					for _, mv := range qv.MaterielList {
						mv.Id = 0
						mv.FlavorSpecificationsId = rfsv.Id
						mv.CreatedAt = time.Now()
						mv.UpdatedAt = time.Now()
						x.Insert(mv)
					}
				}
			}

			wg.Done()
		}()
	}

	wg.Wait()

	return map[string]interface{}{"message":"成功", "code":200}, nil
}